package com.yytek.upgrade.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.yytek.common.core.constant.Constants;
import com.yytek.common.core.domain.DeviceCache;
import com.yytek.common.core.domain.R;
import com.yytek.common.core.utils.CronUtil;
import com.yytek.common.core.utils.DateUtils;
import com.yytek.common.core.utils.bean.BeanCopyUtils;
import com.yytek.common.security.utils.SecurityUtils;
import com.yytek.nmp.api.RemoteJobService;
import com.yytek.nmp.api.RemoteNmpService;
import com.yytek.nmp.api.domain.SysJob;
import com.yytek.upgrade.domain.UpgradeFirmware;
import com.yytek.upgrade.domain.UpgradeHistory;
import com.yytek.upgrade.domain.UpgradeStrategyDeviceTopo;
import com.yytek.upgrade.dto.UpgeadeStrategyDevice;
import com.yytek.upgrade.mapper.UpgradeFirmwareMapper;
import com.yytek.upgrade.mapper.UpgradeHistoryMapper;
import com.yytek.upgrade.mapper.UpgradeStrategyDeviceTopoMapper;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yytek.upgrade.mapper.UpgradeStrategyMapper;
import com.yytek.upgrade.domain.UpgradeStrategy;
import com.yytek.upgrade.service.IUpgradeStrategyService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 升级策略Service业务层处理
 * 
 * @author yytek-iot
 * @date 2022-09-06
 */
@Service
public class UpgradeStrategyServiceImpl implements IUpgradeStrategyService 
{
    @Autowired
    private UpgradeStrategyMapper upgradeStrategyMapper;
    @Autowired
    private UpgradeFirmwareMapper upgradeFirmwareMapper;
    @Autowired
    private UpgradeHistoryMapper upgradeHistoryMapper;
    @Autowired
    private UpgradeStrategyDeviceTopoMapper upgradeStrategyDeviceTopoMapper;
    @Autowired
    private RemoteJobService remoteJobService;
    @Resource
    private RemoteNmpService remoteNmpService;
    /**
     * 查询升级策略
     * 
     * @param id 升级策略主键
     * @return 升级策略
     */
    @Override
    public UpgradeStrategy selectUpgradeStrategyById(Long id)
    {
        return upgradeStrategyMapper.selectUpgradeStrategyById(id);
    }

    /**
     * 查询升级策略列表
     * 
     * @param upgradeStrategy 升级策略
     * @return 升级策略
     */
    @Override
    public List<UpgradeStrategy> selectUpgradeStrategyList(UpgradeStrategy upgradeStrategy)
    {
        return upgradeStrategyMapper.selectUpgradeStrategyList(upgradeStrategy);
    }

    /**
     * 新增升级策略
     * 
     * @param upgradeStrategy 升级策略
     * @return 结果
     */
    @Override
    public int insertUpgradeStrategy(UpgradeStrategy upgradeStrategy)
    {
        upgradeStrategy.setCreateBy(String.valueOf(SecurityUtils.getUserId()));
        upgradeStrategy.setCreateTime(DateUtils.getNowDate());
        return upgradeStrategyMapper.insertUpgradeStrategy(upgradeStrategy);
    }

    /**
     * 修改升级策略
     * 
     * @param upgradeStrategy 升级策略
     * @return 结果
     */
    @Override
    public int updateUpgradeStrategy(UpgradeStrategy upgradeStrategy)
    {
        return upgradeStrategyMapper.updateUpgradeStrategy(upgradeStrategy);
    }

    /**
     * 批量删除升级策略
     * 
     * @param ids 需要删除的升级策略主键
     * @return 结果
     */
    @Override
    public int deleteUpgradeStrategyByIds(Long[] ids)
    {
        return upgradeStrategyMapper.deleteUpgradeStrategyByIds(ids);
    }

    /**
     * 删除升级策略信息
     * 
     * @param id 升级策略主键
     * @return 结果
     */
    @Override
    public int deleteUpgradeStrategyById(Long id)
    {
        return upgradeStrategyMapper.deleteUpgradeStrategyById(id);
    }

    /**
     * 新增升级策略和绑定设备
     * @param upgeadeStrategyDevice
     * @return
     */
    @Override
    @GlobalTransactional
    public int addAndBindDevice(UpgeadeStrategyDevice upgeadeStrategyDevice) {
        //新增保存升级策略
        UpgradeStrategy upgradeStrategy = upgeadeStrategyDevice.getUpgradeStrategy();
        upgradeStrategy.setCreateBy(String.valueOf(SecurityUtils.getUserId()));
        upgradeStrategy.setCreateTime(DateUtils.getNowDate());
        upgradeStrategyMapper.insertUpgradeStrategy(upgradeStrategy);

        Long strategyId =  upgradeStrategy.getId();
        //批量保存绑定设备
        List<UpgradeStrategyDeviceTopo> deviceTopoList = upgeadeStrategyDevice.getTopoList();
        if(CollectionUtil.isNotEmpty(deviceTopoList)){
            List<UpgradeStrategyDeviceTopo> insertData = new ArrayList<>();
            //循环加入策略id
            for (int i = 0; i < deviceTopoList.size(); i++) {
                UpgradeStrategyDeviceTopo deviceTopo = deviceTopoList.get(i);
                deviceTopo.setStrategyId(strategyId);
                insertData.add(deviceTopo);
            }
            upgradeStrategyDeviceTopoMapper.batchUpgradeStrategyDeviceTopo(insertData);
            //批量生成设备升级任务记录
            createStrategyHistory(insertData,upgradeStrategy);
        }
        //生成策略的执行任务
        createStrategyTask(upgradeStrategy);
        return 1;
    }
    /**
     * 批量生成设备升级任务记录
     * @param upgradeStrategy
     */
    public void createStrategyHistory(List<UpgradeStrategyDeviceTopo> upgradeStrategyDeviceTopos,
                                      UpgradeStrategy upgradeStrategy) {
        //插入历史记录列表
        List<UpgradeHistory> insertHistory = new ArrayList<>();
        for (int i = 0; i < upgradeStrategyDeviceTopos.size(); i++) {
            //获取设备id
            String iotId = upgradeStrategyDeviceTopos.get(i).getDeviceId();
            if(remoteNmpService.getDeviceCache(iotId) != null
                    && remoteNmpService.getDeviceCache(iotId).getData() != null ){
                //获取设备缓存
                DeviceCache deviceCache = BeanCopyUtils.mapToBean((Map<String, Object>)
                        remoteNmpService.getDeviceCache(iotId).getData(), DeviceCache.class);
                if(deviceCache != null){
                    //创建升级记录
                    UpgradeHistory upgradeHistory = new UpgradeHistory();
                    upgradeHistory.setStrategyId(upgradeStrategy.getId());
                    upgradeHistory.setUserId(upgradeStrategy.getCreateBy());
                    upgradeHistory.setProductId(Long.valueOf(deviceCache.getProductId()));
                    upgradeHistory.setDeviceId(iotId);
                    upgradeHistory.setDeviceName(iotId);
                    upgradeHistory.setExecuteTime(new Date());
                    //执行策略名称
                    upgradeHistory.setExecuteContent(upgradeStrategy.getName());
                    //执行状态(0:未执行,1:执行中,2:成功,3:失败,4:超时,5:操作冲突)
                    upgradeHistory.setExecStatus(0);
                    insertHistory.add(upgradeHistory);
                }
            }
        }
        //批量插入数据库
        if(CollectionUtil.isNotEmpty(insertHistory)){
            upgradeHistoryMapper.batchUpgradeHistory(insertHistory);
        }
    }
    /**
     * 根据策略id获取升级包
     * @param id
     * @return
     */
    @Override
    public UpgradeFirmware getUpgradeFileByStrategyId(Long id) {
        UpgradeStrategy upgradeStrategy = selectUpgradeStrategyById(id);
        UpgradeFirmware upgradeFirmware = upgradeFirmwareMapper.selectUpgradeFirmwareById(upgradeStrategy.getUpgradeFirmwareId());
        return upgradeFirmware;
    }

    /**
     * 生成升级策略的执行任务
     * @param upgradeStrategy
     */
    public void createStrategyTask(UpgradeStrategy upgradeStrategy) {
        //根据策略不同生成不同任务
        SysJob sysJob = new SysJob();
        //执行策略 0=默认,1=立即触发执行,2=触发一次执行,3=不触发立即执行
        String misfirePolicy = "0";
        //如果是立即执行
        if(upgradeStrategy.getStrategy() == 1){
            misfirePolicy = "3";
            //当天现在时间
            String cronEx = CronUtil.onlyOnce(DateUtil.now());
            sysJob.setCronExpression(cronEx);
        }else{
            //如果sysJob是定时执行
            //解析时间转换成执行字符串
            //仅一次   05 06 11 31 03 ? 2022
            String cronEx = CronUtil.onlyOnce(DateUtil.formatDateTime(upgradeStrategy.getExecuteTime()));
            sysJob.setCronExpression(cronEx);
        }
        //执行策略
        sysJob.setMisfirePolicy(misfirePolicy);
        sysJob.setJobName(upgradeStrategy.getName());
        sysJob.setJobGroup(upgradeStrategy.getId().toString());
        //暂定升级策略id为设备id
        sysJob.setDeviceId(upgradeStrategy.getId().toString());
        sysJob.setTemplateId(upgradeStrategy.getId());
        //执行任务方法
        String exeMethod = "upGrade.strategy('"+upgradeStrategy.getId().toString()+"')";
        sysJob.setInvokeTarget(exeMethod);
        //是否并发执行（0允许 1禁止）
        sysJob.setConcurrent("1");
        //任务状态（0正常 1暂停）
        sysJob.setStatus("0");
        //任务类型 (1-状态采集 2-配置采集 3-操作采集)
        sysJob.setTaskType(3);
        //生成任务
        R r = remoteJobService.addApi(sysJob);
        if(r.getCode() != Constants.SUCCESS){
            //抛出异常
            throw new RuntimeException(r.getMsg());
        }
    }
}
